using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using JGSY.CMS.LowCode.Platform.Infrastructure.Repositories;
using JGSY.CMS.LowCode.Platform.Infrastructure.Configuration;

namespace JGSY.CMS.LowCode.Platform.Application.Services
{
    /// <summary>
    /// 内容应用服务实现 - 完整的动态内容管理服务
    /// 支持动态内容模型、字段管理、内容项CRUD、状态管理等核心功能
    /// </summary>
    public class ContentAppService : IContentAppService
    {
        private readonly IContentRepository _contentRepository;
        private readonly ILogger<ContentAppService> _logger;

        public ContentAppService(
            IContentRepository contentRepository,
            ILogger<ContentAppService> logger)
        {
            _contentRepository = contentRepository ?? throw new ArgumentNullException(nameof(contentRepository));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        #region 内容模型管理

        /// <summary>
        /// 获取所有内容模型
        /// </summary>
        /// <returns>内容模型列表</returns>
        public async Task<IEnumerable<ContentModelDto>> GetAllModelsAsync()
        {
            try
            {
                _logger.LogInformation("获取所有内容模型");
                
                var models = await _contentRepository.GetAllModelsAsync();
                return models.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取内容模型列表失败");
                throw;
            }
        }

        /// <summary>
        /// 根据ID获取内容模型
        /// </summary>
        /// <param name="id">模型标识符</param>
        /// <returns>内容模型信息</returns>
        public async Task<ContentModelDto?> GetModelByIdAsync(long id)
        {
            try
            {
                _logger.LogInformation("获取内容模型，ID: {Id}", id);
                
                var model = await _contentRepository.GetModelByIdAsync(id);
                return model == null ? null : MapToDto(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取内容模型失败，ID: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 创建内容模型
        /// </summary>
        /// <param name="model">内容模型数据传输对象</param>
        /// <returns>创建任务</returns>
        public async Task CreateModelAsync(ContentModelDto model)
        {
            if (model == null) throw new ArgumentNullException(nameof(model));
            
            try
            {
                _logger.LogInformation("创建内容模型: {Name}", model.Name);
                
                var entity = new ContentModel
                {
                    Name = model.Name,
                    Description = model.Description,
                    Fields = JsonSerializer.Serialize(model.Fields ?? new List<FieldDto>()),
                    IsActive = true,
                    AuthorId = 1 // TODO: 从当前用户上下文获取
                };

                await _contentRepository.CreateModelAsync(entity);
                
                _logger.LogInformation("内容模型创建成功: {Name}", model.Name);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建内容模型失败: {Name}", model.Name);
                throw;
            }
        }

        /// <summary>
        /// 更新内容模型
        /// </summary>
        /// <param name="id">模型标识符</param>
        /// <param name="model">内容模型数据传输对象</param>
        /// <returns>更新任务</returns>
        public async Task UpdateModelAsync(long id, ContentModelDto model)
        {
            if (model == null) throw new ArgumentNullException(nameof(model));
            
            try
            {
                _logger.LogInformation("更新内容模型: {Id}", id);
                
                var entity = new ContentModel
                {
                    Id = id,
                    Name = model.Name,
                    Description = model.Description,
                    Fields = JsonSerializer.Serialize(model.Fields ?? new List<FieldDto>()),
                    IsActive = true
                };

                await _contentRepository.UpdateModelAsync(id, entity);
                
                _logger.LogInformation("内容模型更新成功: {Id}", id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新内容模型失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 删除内容模型
        /// </summary>
        /// <param name="id">模型标识符</param>
        /// <returns>删除任务</returns>
        public async Task DeleteModelAsync(long id)
        {
            try
            {
                _logger.LogInformation("删除内容模型: {Id}", id);
                
                await _contentRepository.DeleteModelAsync(id);
                
                _logger.LogInformation("内容模型删除成功: {Id}", id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除内容模型失败: {Id}", id);
                throw;
            }
        }

        #endregion

        #region 字段管理

        /// <summary>
        /// 获取指定模型的所有字段
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <returns>字段列表</returns>
        public async Task<IEnumerable<FieldDto>> GetFieldsAsync(long modelId)
        {
            try
            {
                _logger.LogInformation("获取模型字段，ModelId: {ModelId}", modelId);
                
                var fields = await _contentRepository.GetFieldsAsync(modelId);
                return fields.Select(MapFieldToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取模型字段失败，ModelId: {ModelId}", modelId);
                throw;
            }
        }

        /// <summary>
        /// 为模型添加字段
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="field">字段数据传输对象</param>
        /// <returns>添加任务</returns>
        public async Task AddFieldAsync(long modelId, FieldDto field)
        {
            if (field == null) throw new ArgumentNullException(nameof(field));
            
            try
            {
                _logger.LogInformation("为模型添加字段，ModelId: {ModelId}, FieldName: {FieldName}", 
                    modelId, field.Name);
                
                var entity = MapFieldToEntity(field);
                entity.ContentModelId = modelId;
                
                await _contentRepository.AddFieldAsync(modelId, entity);
                
                _logger.LogInformation("字段添加成功，ModelId: {ModelId}, FieldName: {FieldName}", 
                    modelId, field.Name);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "添加字段失败，ModelId: {ModelId}, FieldName: {FieldName}", 
                    modelId, field.Name);
                throw;
            }
        }

        /// <summary>
        /// 更新模型字段
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="fieldId">字段标识符</param>
        /// <param name="field">字段数据传输对象</param>
        /// <returns>更新任务</returns>
        public async Task UpdateFieldAsync(long modelId, long fieldId, FieldDto field)
        {
            if (field == null) throw new ArgumentNullException(nameof(field));
            
            try
            {
                _logger.LogInformation("更新字段，ModelId: {ModelId}, FieldId: {FieldId}", 
                    modelId, fieldId);
                
                var entity = MapFieldToEntity(field);
                entity.Id = fieldId;
                entity.ContentModelId = modelId;
                
                await _contentRepository.UpdateFieldAsync(modelId, fieldId, entity);
                
                _logger.LogInformation("字段更新成功，ModelId: {ModelId}, FieldId: {FieldId}", 
                    modelId, fieldId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新字段失败，ModelId: {ModelId}, FieldId: {FieldId}", 
                    modelId, fieldId);
                throw;
            }
        }

        /// <summary>
        /// 删除模型字段
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="fieldId">字段标识符</param>
        /// <returns>删除任务</returns>
        public async Task DeleteFieldAsync(long modelId, long fieldId)
        {
            try
            {
                _logger.LogInformation("删除字段，ModelId: {ModelId}, FieldId: {FieldId}", 
                    modelId, fieldId);
                
                await _contentRepository.DeleteFieldAsync(modelId, fieldId);
                
                _logger.LogInformation("字段删除成功，ModelId: {ModelId}, FieldId: {FieldId}", 
                    modelId, fieldId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除字段失败，ModelId: {ModelId}, FieldId: {FieldId}", 
                    modelId, fieldId);
                throw;
            }
        }

        #endregion

        #region 内容项管理

        /// <summary>
        /// 分页获取内容项
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="page">页码，默认为1</param>
        /// <param name="limit">每页数量，默认为10</param>
        /// <returns>内容项列表</returns>
        public async Task<IEnumerable<ContentItemDto>> GetItemsAsync(long modelId, int page = 1, int limit = 10)
        {
            try
            {
                _logger.LogInformation("获取内容项，ModelId: {ModelId}, Page: {Page}, Limit: {Limit}", 
                    modelId, page, limit);
                
                var items = await _contentRepository.GetItemsAsync(modelId, page, limit);
                return items.Select(MapItemToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取内容项失败，ModelId: {ModelId}", modelId);
                throw;
            }
        }

        /// <summary>
        /// 创建内容项
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="item">内容项数据传输对象</param>
        /// <returns>创建任务</returns>
        public async Task CreateItemAsync(long modelId, ContentItemDto item)
        {
            if (item == null) throw new ArgumentNullException(nameof(item));
            
            try
            {
                _logger.LogInformation("创建内容项，ModelId: {ModelId}", modelId);
                
                // 验证字段数据
                var validation = await ValidateFieldDataAsync(modelId, item.Data);
                if (!validation.IsValid)
                {
                    throw new ArgumentException($"字段验证失败: {string.Join(", ", validation.Errors)}");
                }
                
                var entity = new ContentItem
                {
                    ModelId = modelId,
                    Title = ExtractTitleFromData(item.Data),
                    Data = JsonSerializer.Serialize(item.Data ?? new Dictionary<string, object>()),
                    Status = string.IsNullOrEmpty(item.Status) ? "draft" : item.Status
                };

                await _contentRepository.CreateItemAsync(modelId, entity);
                
                _logger.LogInformation("内容项创建成功，ModelId: {ModelId}", modelId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建内容项失败，ModelId: {ModelId}", modelId);
                throw;
            }
        }

        /// <summary>
        /// 根据ID获取内容项
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="itemId">内容项标识符</param>
        /// <returns>内容项信息</returns>
        public async Task<ContentItemDto?> GetItemByIdAsync(long modelId, long itemId)
        {
            try
            {
                _logger.LogInformation("获取内容项，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
                
                var item = await _contentRepository.GetItemByIdAsync(modelId, itemId);
                return item == null ? null : MapItemToDto(item);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取内容项失败，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
                throw;
            }
        }

        /// <summary>
        /// 更新内容项
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="itemId">内容项标识符</param>
        /// <param name="item">内容项数据传输对象</param>
        /// <returns>更新任务</returns>
        public async Task UpdateItemAsync(long modelId, long itemId, ContentItemDto item)
        {
            if (item == null) throw new ArgumentNullException(nameof(item));
            
            try
            {
                _logger.LogInformation("更新内容项，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
                
                // 验证字段数据
                var validation = await ValidateFieldDataAsync(modelId, item.Data);
                if (!validation.IsValid)
                {
                    throw new ArgumentException($"字段验证失败: {string.Join(", ", validation.Errors)}");
                }
                
                var entity = new ContentItem
                {
                    Id = itemId,
                    ModelId = modelId,
                    Title = ExtractTitleFromData(item.Data),
                    Data = JsonSerializer.Serialize(item.Data ?? new Dictionary<string, object>()),
                    Status = item.Status ?? "draft"
                };

                await _contentRepository.UpdateItemAsync(modelId, itemId, entity);
                
                _logger.LogInformation("内容项更新成功，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新内容项失败，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
                throw;
            }
        }

        /// <summary>
        /// 删除内容项
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="itemId">内容项标识符</param>
        /// <returns>删除任务</returns>
        public async Task DeleteItemAsync(long modelId, long itemId)
        {
            try
            {
                _logger.LogInformation("删除内容项，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
                
                await _contentRepository.DeleteItemAsync(modelId, itemId);
                
                _logger.LogInformation("内容项删除成功，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除内容项失败，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
                throw;
            }
        }

        /// <summary>
        /// 获取内容项状态
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="itemId">内容项标识符</param>
        /// <returns>状态信息</returns>
        public async Task<object?> GetItemStatusAsync(long modelId, long itemId)
        {
            try
            {
                _logger.LogInformation("获取内容项状态，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
                
                var item = await _contentRepository.GetItemByIdAsync(modelId, itemId);
                return item?.Status;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取内容项状态失败，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
                throw;
            }
        }

        /// <summary>
        /// 更改内容项状态
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="itemId">内容项标识符</param>
        /// <param name="status">新状态</param>
        /// <returns>状态更改任务</returns>
        public async Task ChangeItemStatusAsync(long modelId, long itemId, string status)
        {
            if (string.IsNullOrEmpty(status)) throw new ArgumentException("状态不能为空", nameof(status));
            
            try
            {
                _logger.LogInformation("更改内容项状态，ModelId: {ModelId}, ItemId: {ItemId}, Status: {Status}", 
                    modelId, itemId, status);
                
                var item = await _contentRepository.GetItemByIdAsync(modelId, itemId);
                if (item != null)
                {
                    item.Status = status;
                    await _contentRepository.UpdateItemAsync(modelId, itemId, item);
                }
                else
                {
                    throw new InvalidOperationException($"内容项不存在，ModelId: {modelId}, ItemId: {itemId}");
                }
                
                _logger.LogInformation("内容项状态更改成功，ModelId: {ModelId}, ItemId: {ItemId}, Status: {Status}", 
                    modelId, itemId, status);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更改内容项状态失败，ModelId: {ModelId}, ItemId: {ItemId}", 
                    modelId, itemId);
                throw;
            }
        }

        #endregion

        #region 扩展功能

        /// <summary>
        /// 验证字段数据
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="data">数据字典</param>
        /// <returns>验证结果</returns>
        public async Task<(bool IsValid, List<string> Errors)> ValidateFieldDataAsync(
            long modelId, 
            Dictionary<string, object> data)
        {
            try
            {
                var errors = new List<string>();
                var fields = await _contentRepository.GetFieldsAsync(modelId);
                
                foreach (var field in fields)
                {
                    // 必填验证
                    if (field.IsRequired && (!data.ContainsKey(field.Name) || data[field.Name] == null))
                    {
                        errors.Add($"字段 '{field.Label ?? field.Name}' 是必填字段");
                        continue;
                    }
                    
                    // 类型验证
                    if (data.ContainsKey(field.Name) && data[field.Name] != null)
                    {
                        var value = data[field.Name].ToString();
                        if (!ValidateFieldValue(field, value!))
                        {
                            errors.Add($"字段 '{field.Label ?? field.Name}' 的值不符合格式要求");
                        }
                    }
                }
                
                return (errors.Count == 0, errors);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "验证字段数据失败，ModelId: {ModelId}", modelId);
                return (false, new List<string> { "验证过程中发生错误" });
            }
        }

        /// <summary>
        /// 批量更新内容项状态
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <param name="itemIds">内容项ID列表</param>
        /// <param name="status">新状态</param>
        /// <returns>更新任务</returns>
        public async Task BatchUpdateItemStatusAsync(long modelId, List<long> itemIds, string status)
        {
            if (itemIds == null || !itemIds.Any()) throw new ArgumentException("内容项ID列表不能为空", nameof(itemIds));
            if (string.IsNullOrEmpty(status)) throw new ArgumentException("状态不能为空", nameof(status));
            
            try
            {
                _logger.LogInformation("批量更新内容项状态，ModelId: {ModelId}, Count: {Count}, Status: {Status}", 
                    modelId, itemIds.Count, status);

                if (_contentRepository is ContentRepository repository)
                {
                    await repository.BatchUpdateItemStatusAsync(modelId, itemIds, status);
                }
                else
                {
                    // 回退到逐个更新
                    foreach (var itemId in itemIds)
                    {
                        await ChangeItemStatusAsync(modelId, itemId, status);
                    }
                }
                
                _logger.LogInformation("批量状态更新完成，ModelId: {ModelId}, Count: {Count}", 
                    modelId, itemIds.Count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量更新内容项状态失败，ModelId: {ModelId}", modelId);
                throw;
            }
        }

        /// <summary>
        /// 获取内容项统计信息
        /// </summary>
        /// <param name="modelId">模型标识符</param>
        /// <returns>统计信息</returns>
        public async Task<Dictionary<string, object>> GetContentStatisticsAsync(long modelId)
        {
            try
            {
                _logger.LogInformation("获取内容统计信息，ModelId: {ModelId}", modelId);
                
                var statistics = new Dictionary<string, object>();

                if (_contentRepository is ContentRepository repository)
                {
                    var totalCount = await repository.GetItemsCountAsync(modelId);
                    var draftItems = await repository.GetItemsByStatusAsync(modelId, "draft");
                    var publishedItems = await repository.GetItemsByStatusAsync(modelId, "published");
                    var archivedItems = await repository.GetItemsByStatusAsync(modelId, "archived");

                    statistics["total"] = totalCount;
                    statistics["draft"] = draftItems.Count();
                    statistics["published"] = publishedItems.Count();
                    statistics["archived"] = archivedItems.Count();
                    statistics["modelId"] = modelId;
                    statistics["lastUpdated"] = DateTime.UtcNow;
                }

                return statistics;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取内容统计信息失败，ModelId: {ModelId}", modelId);
                throw;
            }
        }

        #endregion

        #region 私有辅助方法

        /// <summary>
        /// 映射内容模型实体到DTO
        /// </summary>
        private ContentModelDto MapToDto(ContentModel model)
        {
            var dto = new ContentModelDto
            {
                Id = model.Id,
                Name = model.Name,
                Description = model.Description,
                Fields = new List<FieldDto>()
            };

            if (!string.IsNullOrEmpty(model.Fields))
            {
                try
                {
                    dto.Fields = JsonSerializer.Deserialize<List<FieldDto>>(model.Fields) ?? new List<FieldDto>();
                }
                catch (JsonException ex)
                {
                    _logger.LogWarning(ex, "反序列化字段失败，ModelId: {ModelId}", model.Id);
                }
            }

            return dto;
        }

        /// <summary>
        /// 映射字段实体到DTO
        /// </summary>
        private FieldDto MapFieldToDto(Field field)
        {
            return new FieldDto
            {
                Id = field.Id,
                Name = field.Name,
                Type = field.Type,
                Label = field.Label,
                IsRequired = field.IsRequired,
                DefaultValue = field.DefaultValue,
                Options = field.Options,
                ValidationRules = field.ValidationRules
            };
        }

        /// <summary>
        /// 映射字段DTO到实体
        /// </summary>
        private Field MapFieldToEntity(FieldDto dto)
        {
            return new Field
            {
                Id = dto.Id,
                Name = dto.Name,
                Type = dto.Type,
                Label = dto.Label,
                IsRequired = dto.IsRequired,
                DefaultValue = dto.DefaultValue,
                Options = dto.Options,
                ValidationRules = dto.ValidationRules,
                Order = 0,
                IsActive = true
            };
        }

        /// <summary>
        /// 映射内容项实体到DTO
        /// </summary>
        private ContentItemDto MapItemToDto(ContentItem item)
        {
            var dto = new ContentItemDto
            {
                Id = item.Id,
                ModelId = item.ModelId,
                Status = item.Status,
                Data = new Dictionary<string, object>()
            };

            if (!string.IsNullOrEmpty(item.Data))
            {
                try
                {
                    dto.Data = JsonSerializer.Deserialize<Dictionary<string, object>>(item.Data) 
                        ?? new Dictionary<string, object>();
                }
                catch (JsonException ex)
                {
                    _logger.LogWarning(ex, "反序列化内容项数据失败，ItemId: {ItemId}", item.Id);
                }
            }

            return dto;
        }

        /// <summary>
        /// 从数据中提取标题
        /// </summary>
        private string ExtractTitleFromData(Dictionary<string, object> data)
        {
            if (data == null) return "无标题";
            
            // 尝试从常见的字段名获取标题
            var titleKeys = new[] { "title", "name", "subject", "heading", "label" };
            
            foreach (var key in titleKeys)
            {
                if (data.ContainsKey(key) && data[key] != null)
                {
                    return data[key].ToString() ?? string.Empty;
                }
            }

            // 如果没有找到，使用第一个字符串值
            var firstStringValue = data.Values.FirstOrDefault(v => v is string);
            return firstStringValue?.ToString() ?? "无标题";
        }

        /// <summary>
        /// 验证字段值格式
        /// </summary>
        private bool ValidateFieldValue(Field field, string value)
        {
            if (string.IsNullOrEmpty(value) || field.Type == null) return true;
            
            // 使用统一配置处理器进行字段验证
            var result = UnifiedConfigurationProcessor.ValidateFieldValue(field.Type, value);
            
            if (!result.IsValid)
            {
                _logger.LogWarning("字段验证失败: {FieldName}, Type: {FieldType}, Value: {Value}, Error: {Error}", 
                    field.Name, field.Type, value, result.ErrorMessage);
            }
            
            return result.IsValid;
        }

        /// <summary>
        /// 验证邮箱格式
        /// </summary>
        private bool IsValidEmail(string email)
        {
            try
            {
                var addr = new System.Net.Mail.MailAddress(email);
                return addr.Address == email;
            }
            catch
            {
                return false;
            }
        }

        #endregion
    }
}
